package com.copyurl.util;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import org.apache.commons.collections.CollectionUtils;

import java.util.*;
import java.util.function.BooleanSupplier;

import static com.intellij.openapi.actionSystem.LangDataKeys.EDITOR;
import static com.intellij.openapi.actionSystem.LangDataKeys.PSI_FILE;


public class Actions {

    /**
     * 根据名字获取指定psiFile文件
     *
     * @param e    事件
     * @param name 名称
     * @return psiFile
     */
    public static PsiFile getPsiFileByName(AnActionEvent e, String name) {
        Project project = e.getData(CommonDataKeys.PROJECT);
        if (project == null) {
            return e.getData(PSI_FILE);
        }
        Collection<VirtualFile> virtualFilesByName = FilenameIndex.getVirtualFilesByName(name, GlobalSearchScope.allScope(project));
        List<VirtualFile> virtualFileList = new ArrayList<>(virtualFilesByName);
        if (CollectionUtils.isNotEmpty(virtualFileList)) {
            VirtualFile virtualFile = virtualFileList.get(0);
            return PsiManager.getInstance(project).findFile(virtualFile);
        }
        return e.getData(PSI_FILE);
    }

    /**
     * 获取当前正在编辑行的elem
     *
     * @param e AnActionEvent
     * @return PsiElement
     */
    public static PsiElement getCurrentEditorElement(AnActionEvent e) {
        Editor editor = e.getData(EDITOR);
        if (editor == null) {
            return null;
        }
        PsiFile psiFile = e.getData(PSI_FILE);
        if (psiFile == null) {
            return null;
        }
        return psiFile.findElementAt(editor.getCaretModel().getOffset());
    }

    /**
     * 检测当前 PsiClass 是否含有`RestController` | `Controller` | `Path`
     *
     * @param psiMethod psiMethod
     * @return bool
     */
    public static boolean hasRestful(PsiMethod psiMethod) {
        if (psiMethod == null) {
            return false;
        }
        PsiClass psiClass = psiMethod.getContainingClass();
        if (psiClass == null) {
            return false;
        }
        return SpringUtil.isRestMethod(psiClass.getModifierList());
    }

    /**
     * 获取当前PsiCLass
     *
     * @param event AnActionEvent
     * @return PsiClass
     */
    public static List<PsiClass> getPsiClass(AnActionEvent event) {
        PsiElement currentEditorElement = getCurrentEditorElement(event);
        if (currentEditorElement != null) {
            PsiFile containingFile = currentEditorElement.getContainingFile();
            if (containingFile instanceof PsiJavaFile psiJavaFile) {
                return Arrays.stream(psiJavaFile.getClasses()).toList();
            }
        }
        return Collections.emptyList();
    }

    /**
     * 获取当前选择的PsiMethod
     *
     * @param event AnActionEvent
     * @return PsiMethod
     */

    public static PsiMethod getPsiMethod(AnActionEvent event) {
        PsiElement currentEditorElement = getCurrentEditorElement(event);
        if (currentEditorElement == null) {
            return null;
        }
        // 如果右键处为当前方法其中的 注解末尾 或 方法体中
        PsiElement editorElementContext = currentEditorElement.getContext();
        if (editorElementContext instanceof PsiMethod) {
            return ((PsiMethod) editorElementContext);
        }
        return null;
    }

    /**
     * 是否包含PsiClass
     *
     * @param event AnActionEvent
     * @return bool
     */
    public static boolean withPsiClass(AnActionEvent event) {
        if (event.getProject() == null) {
            return false;
        }
        for (PsiClass psiClass : getPsiClass(event)) {
            if (SpringUtil.isRestMethod(psiClass.getModifierList())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否包含PsiMethod
     *
     * @param event AnActionEvent
     * @return bool
     */
    public static boolean withPsiMethod(AnActionEvent event) {
        if (event.getProject() == null) {
            return false;
        }
        return hasRestful(getPsiMethod(event));
    }

    public static void enabled(AnActionEvent event, BooleanSupplier condition) {
        Project project = event.getProject();
        if (project == null) {
            return;
        }
        event.getPresentation().setEnabled(condition.getAsBoolean());
    }
}
